package net.risesoft.api.org;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import net.risesoft.entity.Y9OrgBase;
import net.risesoft.entity.Y9Person;
import net.risesoft.entity.Y9Position;
import net.risesoft.manager.Y9OrgBaseManager;
import net.risesoft.model.OrgUnit;
import net.risesoft.model.Person;
import net.risesoft.model.Position;
import net.risesoft.service.org.Y9PersonService;
import net.risesoft.service.org.Y9PositionService;
import net.risesoft.service.relation.Y9PersonsToPositionsService;
import net.risesoft.util.ModelConvertUtil;
import net.risesoft.y9.Y9LoginUserHolder;

/**
 * 岗位服务组件
 *
 * @author dingzhaojun
 * @author qinman
 * @author mengjuhua
 * @date 2022/2/10
 * @since 9.6.0
 */
@Primary
@RestController
@RequestMapping(value = "/services/rest/position", produces = MediaType.APPLICATION_JSON_VALUE)
@Slf4j
@RequiredArgsConstructor
public class PositionApiImpl implements PositionApi {

    private final Y9OrgBaseManager y9OrgBaseManager;
    private final Y9PersonService orgPersonService;
    private final Y9PositionService orgPositionService;
    private final Y9PersonsToPositionsService orgPositionsPersonsService;

    /**
     * 岗位增加人员
     *
     * @param tenantId 租户id
     * @param positionId 岗位id
     * @param personId 人员id
     * @return boolean true 移除成功，false 移除失败
     * @since 9.6.0
     */
    @Override
    @PostMapping("/addPerson")
    public boolean addPerson(@RequestParam String tenantId, @RequestParam String positionId, @RequestParam String personId) {
        if (StringUtils.isBlank(tenantId) || StringUtils.isBlank(positionId) || StringUtils.isBlank(personId)) {
            return false;
        }
        Y9LoginUserHolder.setTenantId(tenantId);
        if (orgPositionService.existsById(positionId) && orgPersonService.existsById(personId)) {
            orgPositionsPersonsService.addPersons(positionId, new String[] {personId});
            return true;
        }
        return false;
    }

    /**
     * 创建岗位
     *
     * @param tenantId 租户id
     * @param positionJson 岗位对象
     * @return Position 岗位对象
     * @since 9.6.0
     */
    @Override
    @PostMapping("/createPosition")
    public Position createPosition(@RequestParam String tenantId, @RequestParam String positionJson) {
        if (StringUtils.isBlank(tenantId) || StringUtils.isBlank(positionJson)) {
            return null;
        }
        Y9LoginUserHolder.setTenantId(tenantId);
        ObjectMapper om = new ObjectMapper();
        try {
            JsonNode jn = om.readTree(positionJson);
            om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            SimpleDateFormat myFmt2 = new SimpleDateFormat("yyyy-MM-dd");
            om.setDateFormat(myFmt2);
            Y9Position y9Position = om.readValue(jn.toString(), Y9Position.class);
            ConvertUtils.register(new DateConverter(null), java.util.Date.class);
            y9Position = orgPositionService.createPosition(y9Position, y9OrgBaseManager.getParent(y9Position.getParentId()));
            return ModelConvertUtil.convert(y9Position, Position.class);
        } catch (JsonProcessingException e) {
            LOGGER.warn(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据岗位id删除岗位
     *
     * @param tenantId 租户id
     * @param positionId 岗位id
     * @return boolean s是否删除成功
     * @since 9.6.0
     */
    @Override
    @PostMapping("/deletePosition")
    public boolean deletePosition(@RequestParam String tenantId, @RequestParam String positionId) {
        if (StringUtils.isBlank(positionId)) {
            return false;
        }
        Y9LoginUserHolder.setTenantId(tenantId);
        if (orgPositionService.existsById(positionId)) {
            orgPositionService.deleteById(positionId);
            return true;
        }
        return false;
    }

    /**
     * 获取岗位父节点
     *
     * @param tenantId 租户id
     * @param positionId 岗位唯一标识
     * @return OrgUnit 机构对象
     * @since 9.6.0
     */
    @Override
    @GetMapping("/getParent")
    public OrgUnit getParent(@RequestParam String tenantId, @RequestParam String positionId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        Y9Position y9Position = orgPositionService.getById(positionId);
        Y9OrgBase parent = y9OrgBaseManager.getParent(y9Position.getParentId());
        return ModelConvertUtil.orgBaseToOrgUnit(parent);
    }

    /**
     * 根据id获得岗位对象
     *
     * @param tenantId 租户id
     * @param positionId 岗位唯一标识
     * @return Position 岗位对象
     * @since 9.6.0
     */
    @Override
    @GetMapping("/getPosition")
    public Position getPosition(@RequestParam String tenantId, @RequestParam String positionId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        Y9Position y9Position = orgPositionService.findById(positionId);
        return ModelConvertUtil.convert(y9Position, Position.class);
    }

    /**
     * 根据人员id和岗位id判断该人员是否拥有此岗位
     *
     * @param tenantId 租户id
     * @param positionName 岗位名称
     * @param personId 岗位唯一标识
     * @return boolean 是否拥有该岗位
     * @since 9.6.0
     */
    @Override
    @GetMapping("/hasPosition")
    public boolean hasPosition(@RequestParam String tenantId, @RequestParam String positionName, @RequestParam String personId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        return orgPositionService.hasPosition(positionName, personId);
    }

    /**
     * 根据父节点获取岗位列表
     *
     * @param tenantId 租户唯一标识
     * @param parentId 父节点ID
     * @return List<Position> 岗位对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listByParentId")
    public List<Position> listByParentId(@RequestParam String tenantId, @RequestParam String parentId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Position> orgPositionList = orgPositionService.listByParentId(parentId);
        List<Position> positionList = new ArrayList<>();
        for (Y9Position position : orgPositionList) {
            positionList.add(ModelConvertUtil.convert(position, Position.class));
        }
        return positionList;
    }

    /**
     * 根据用户ID,获取岗位列表
     *
     * @param tenantId 租户唯一标识
     * @param personId 人员ID
     * @return List<Position> 岗位对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listByPersonId")
    public List<Position> listByPersonId(@RequestParam String tenantId, @RequestParam String personId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Position> orgPositionList = orgPositionService.listByPersonId(personId);
        List<Position> positionList = new ArrayList<>();
        for (Y9Position position : orgPositionList) {
            positionList.add(ModelConvertUtil.convert(position, Position.class));
        }
        return positionList;
    }

    /**
     * 获取岗位的人员列表
     *
     * @param tenantId 租户id
     * @param positionId 岗位唯一标识
     * @return List<Person> 人员对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listPersons")
    public List<Person> listPersons(@RequestParam String tenantId, @RequestParam String positionId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Person> orgPersonList = orgPersonService.listByPositionId(positionId);
        List<Person> personList = new ArrayList<>();
        for (Y9Person y9Person : orgPersonList) {
            personList.add(ModelConvertUtil.convert(y9Person, Person.class));
        }
        return personList;
    }

    /**
     * 从岗位移除人员
     *
     * @param tenantId 租户id
     * @param positionId 岗位id
     * @param personId 人员id
     * @return boolean true 移除成功，false 移除失败
     * @since 9.6.0
     */
    @Override
    @PostMapping("/removePerson")
    public boolean removePerson(@RequestParam String tenantId, @RequestParam String positionId, @RequestParam String personId) {
        if (StringUtils.isBlank(tenantId) || StringUtils.isBlank(positionId) || StringUtils.isBlank(personId)) {
            return false;
        }
        Y9LoginUserHolder.setTenantId(tenantId);
        if (orgPositionService.existsById(positionId) && orgPersonService.existsById(personId)) {
            orgPositionsPersonsService.deletePersons(positionId, new String[] {personId});
            return true;
        }

        return false;
    }

    /**
     * 更新岗位
     *
     * @param tenantId 租户id
     * @param positionJson 岗位对象
     * @return Position 岗位对象
     * @since 9.6.0
     */
    @Override
    @PostMapping("/updatePosition")
    public Position updatePosition(@RequestParam String tenantId, @RequestParam String positionJson) {
        if (StringUtils.isBlank(tenantId) || StringUtils.isBlank(positionJson)) {
            return null;
        }
        Y9LoginUserHolder.setTenantId(tenantId);
        ObjectMapper om = new ObjectMapper();
        try {
            JsonNode jn = om.readTree(positionJson);
            om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            SimpleDateFormat myFmt2 = new SimpleDateFormat("yyyy-MM-dd");
            om.setDateFormat(myFmt2);
            Y9Position y9Position = om.readValue(jn.toString(), Y9Position.class);
            y9Position = orgPositionService.saveOrUpdate(y9Position, y9OrgBaseManager.getParent(y9Position.getParentId()));
            return ModelConvertUtil.convert(y9Position, Position.class);
        } catch (JsonProcessingException e) {
            LOGGER.warn(e.getMessage(), e);
            return null;
        }
    }
}
